//#define TC_SHAREWARE

#include <stdlib.h>
#include <time.h>
#include <GL/freeglut.h>
#include <ode/ode.h>
#include <AL/alut.h>
#include <juanmabc.h>
#include "tcGame.h"
#include "tcTrack.h"
#include "tcCheckPoints.h"
#include "tcItems.h"
#include "tcToy.h"
#include "tcStateMain.h"
#include "tcStateOptions.h"
#include "tcStateTrack.h"
#include "tcStateToy.h"
#include "tcStateHelp.h"
#include "tcStateCredits.h"
#include "tcStateRace.h"

void
tcIn()
{
	TCGame *game;
	unsigned int strings[3], sound;

	game = tcGame();

	srand((unsigned int) time(NULL));

	jmbcCreateContext();

	tcToyCreateContext();
	tcItemsCreateContext();
	tcCheckPointsCreateContext();
	tcTrackCreateContext();

	tlGenStrings(3, strings);
	tlStringLoad(strings[0], PACKAGE_DATADIR);

	/*
	{
		ALuint buffer;
		unsigned int sound;

		alGenSources(1, &game->general.music);
		alGenBuffers(1, &buffer);
		slGenSounds(1, &sound);
		tlStringLoad(strings[1], L"Music.ogg");
		tlStringConcatPath(strings[2], 2, strings);
		slSoundLoadVORBIS(sound, strings[2]);
		tlStringsUnload(2, &strings[1]);
		slSoundBufferData(sound, buffer);
		slSoundUnload(sound);
		slDeleteSounds(1, &sound);
		alSourcei(game->general.music, AL_BUFFER, buffer);
		alSourcei(game->general.music, AL_LOOPING, AL_TRUE);
		alSourcePlay(game->general.music);
	}
	*/

	glEnable(GL_DEPTH_TEST);

	glEnable(GL_TEXTURE_2D);

	glEnable(GL_BLEND);
	glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

	//glEnable(GL_COLOR_MATERIAL);
	//glColorMaterial(GL_FRONT, GL_AMBIENT);

	/*
	{
		float ambient[4] = { 0.5f, 0.5f, 0.5f, 1.0f }, diffuse[4] = { 1.0f, 1.0f, 1.0f, 1.0f }, specular[4] = { 1.0f, 1.0f, 1.0f, 1.0f }, position[4] = { 0.0f, 1000.0f, 0.0f, 1.0f };
		position[0] = -1000.0f;
		glLightfv(GL_LIGHT0, GL_AMBIENT, ambient);
		glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse);
		glLightfv(GL_LIGHT0, GL_SPECULAR, specular);
		glLightfv(GL_LIGHT0, GL_POSITION, position);
		glEnable(GL_LIGHT0);
		glEnable(GL_LIGHTING);
	}
	*/

	glShadeModel(GL_SMOOTH);

	glEnable(GL_CULL_FACE);
	glCullFace(GL_BACK);

	//glClearColor(0.0f, 0.0f, 0.4f, 1.0f);

	glLoadIdentity();

	game->general.nfonts = 1;

	tlGenStrings(game->general.nfonts, game->general.fonts);
	tlStringLoad(game->general.fonts[0], L"VeraBd.ttf");

	tlGenStrings(game->general.nfonts, game->general.fontsmat);
	tlStringLoad(game->general.fontsmat[0], L"Font.cmaterial");

	flGenFonts(1, &game->general.font);
	tlStringLoad(strings[1], tlStringData(game->general.fonts[0]));
	tlStringConcatPath(strings[2], 2, strings);
	flFontLoad(game->general.font, strings[2]);
	tlStringsUnload(2, &strings[1]);
	flFontSetPixelSizes(game->general.font, 16, 16);

	mlGenMaterials(1, &game->general.fontmat);
	tlStringLoad(strings[1], tlStringData(game->general.fontsmat[0]));
	tlStringConcatPath(strings[2], 2, strings);
	mlMaterialLoad(game->general.fontmat, strings[2]);
	tlStringsUnload(2, &strings[1]);
	mlMaterialGenTextures(game->general.fontmat, strings[0]);

	game->main.selection = 0;

	mlGenMeshes(1, &game->general.selector);
	tlStringLoad(strings[1], L"Toy1.cmesh");
	tlStringConcatPath(strings[2], 2, strings);
	mlMeshLoad(game->general.selector, strings[2]);
	mlMeshGenMaterials(game->general.selector, strings[0]);
	tlStringsUnload(2, &strings[1]);

	alGenSources(3, game->general.sounds);
	alGenBuffers(3, game->general.buffers);

	slGenSounds(1, &sound);

	tlStringLoad(strings[1], L"beep-08.ogg");
	tlStringConcatPath(strings[2], 2, strings);
	slSoundLoadVORBIS(sound, strings[2]);
	slSoundBufferData(sound, game->general.buffers[0]);
	slSoundUnload(sound);
	alSourcei(game->general.sounds[0], AL_BUFFER, game->general.buffers[0]);
	tlStringsUnload(2, &strings[1]);

	tlStringLoad(strings[1], L"beep-10.ogg");
	tlStringConcatPath(strings[2], 2, strings);
	slSoundLoadVORBIS(sound, strings[2]);
	slSoundBufferData(sound, game->general.buffers[1]);
	slSoundUnload(sound);
	alSourcei(game->general.sounds[1], AL_BUFFER, game->general.buffers[1]);
	tlStringsUnload(2, &strings[1]);

	tlStringLoad(strings[1], L"beep-09.ogg");
	tlStringConcatPath(strings[2], 2, strings);
	slSoundLoadVORBIS(sound, strings[2]);
	slSoundBufferData(sound, game->general.buffers[2]);
	slSoundUnload(sound);
	alSourcei(game->general.sounds[2], AL_BUFFER, game->general.buffers[2]);
	tlStringsUnload(2, &strings[1]);

	slDeleteSounds(1, &sound);

	#ifdef TC_SHAREWARE
	game->general.ntracks = 1;
	#else
	game->general.ntracks = 9;
	#endif
	tlGenStrings(game->general.ntracks, game->general.tracks);
	tlStringLoad(game->general.tracks[0], L"Track1");
	#ifndef TC_SHAREWARE
	tlStringLoad(game->general.tracks[1], L"Track2");
	tlStringLoad(game->general.tracks[2], L"Track3");
	tlStringLoad(game->general.tracks[3], L"Track4");
	tlStringLoad(game->general.tracks[4], L"Track5");
	tlStringLoad(game->general.tracks[5], L"Track6");
	tlStringLoad(game->general.tracks[6], L"Track7");
	tlStringLoad(game->general.tracks[7], L"Track8");
	tlStringLoad(game->general.tracks[8], L"Track9");
	#endif


	tlGenStrings(8, game->general.tcolors);
	tlStringLoad(game->general.tcolors[0], L"Red");
	tlStringLoad(game->general.tcolors[1], L"Green");
	tlStringLoad(game->general.tcolors[2], L"Blue");
	tlStringLoad(game->general.tcolors[3], L"Yellow");
	tlStringLoad(game->general.tcolors[4], L"Orange");
	tlStringLoad(game->general.tcolors[5], L"Cyan");
	tlStringLoad(game->general.tcolors[6], L"Magenta");
	tlStringLoad(game->general.tcolors[7], L"Purple");

	#ifdef TC_SHAREWARE
	game->general.ntoys = 1;
	#else
	game->general.ntoys = 4;
	#endif
	tlGenStrings(game->general.ntoys, game->general.toys);
	tlStringLoad(game->general.toys[0], L"Toy1");
	#ifndef TC_SHAREWARE
	tlStringLoad(game->general.toys[1], L"Toy2");
	tlStringLoad(game->general.toys[2], L"Toy3");
	tlStringLoad(game->general.toys[3], L"Toy4");
	#endif
	
	game->general.nsfxs = 7;
	tlGenStrings(game->general.nsfxs, game->general.sfxs);
	tlStringLoad(game->general.sfxs[0], L"beep-02.ogg");
	tlStringLoad(game->general.sfxs[1], L"beep-03.ogg");
	tlStringLoad(game->general.sfxs[2], L"beep-04.ogg");
	tlStringLoad(game->general.sfxs[3], L"beep-05.ogg");
	tlStringLoad(game->general.sfxs[4], L"beep-06.ogg");
	tlStringLoad(game->general.sfxs[5], L"beep-07.ogg");
	tlStringLoad(game->general.sfxs[6], L"applause-light-01.ogg");

	game->main.nstrs = 4;
	tlGenStrings(game->main.nstrs, game->main.strs);
	tlStringLoad(game->main.strs[0], L"Options");
	tlStringLoad(game->main.strs[1], L"Help");
	#ifdef TC_SHAREWARE
	tlStringLoad(game->main.strs[2], L"Credits (Order)");
	#else
	tlStringLoad(game->main.strs[2], L"Credits");
	#endif
	tlStringLoad(game->main.strs[3], L"Race");

	game->help.nstrs = 9;
	tlGenStrings(game->help.nstrs, game->help.strs);
	tlStringLoad(game->help.strs[0], L"Select Human Or Computer Toys");
	tlStringLoad(game->help.strs[1], L"Select Track And Toy To Race");
	tlStringLoad(game->help.strs[2], L"Screen Off The Toys Or Item Smash Them To Win A Point");
	tlStringLoad(game->help.strs[3], L"Win Enough Points To Win The Race");
	tlStringLoad(game->help.strs[4], L"Colors & Controls:");
	tlStringLoad(game->help.strs[5], L"Player 1 (Red): Keyboard Arrows & Enter");
	tlStringLoad(game->help.strs[6], L"Player 2 (Green): S, X, Z, C & F");
	tlStringLoad(game->help.strs[7], L"Player 3 (Blue): U, J, H, K & P");
	tlStringLoad(game->help.strs[8], L"Player 4 (Yellow): Joystick Pad & Button A");

	game->credits.nstrs = 7;
	tlGenStrings(game->credits.nstrs, game->credits.strs);
	tlStringLoad(game->credits.strs[0], L"ToyCars");
	tlStringLoad(game->credits.strs[1], L"Copyright " PACKAGE_YEAR L" " PACKAGE_AUTHOR);
	#ifdef TC_SHAREWARE
	tlStringLoad(game->credits.strs[2], L"Free Shareware Version - Provided Free Of Charge");
	tlStringLoad(game->credits.strs[3], L"Order Full Version At: juanmabcsoft@gmail.com");
	tlStringLoad(game->credits.strs[4], L"EMail With Subject: Order ToyCars");
	tlStringLoad(game->credits.strs[5], L"Expect Payment Instructions (Mail Check)");
	#else
//	tlStringLoad(game->credits.strs[2], L"Full Commercial Version - Licensed");
//	tlStringLoad(game->credits.strs[3], L"Ordered at: juanmabcsoft@gmail.com");
//	tlStringLoad(game->credits.strs[4], L"Do Not Share or Distribute Without Permission");
//	tlStringLoad(game->credits.strs[5], L"Number Of Tracks: 9, Number Of Toys: 3");
	tlStringLoad(game->credits.strs[2], L"Race Fighting Car Game");
	tlStringLoad(game->credits.strs[3], PACKAGE_HOMEPAGE);
	tlStringLoad(game->credits.strs[4], L"Play & Enjoy!");
	tlStringLoad(game->credits.strs[5], L"Number Of Tracks: 9, Number Of Toys: 3");
	#endif
//	tlStringLoad(game->credits.strs[6], L"Full Version Price: 12 Euros");
	tlStringLoad(game->credits.strs[6], L"Full Free Version - GPL");

	game->options.selection = 0;
	game->options.race.ntoys = 6;
	game->options.race.nplayers = 1;
	game->options.race.npoints = 5;
	game->options.race.speed = 20.0f;
	game->options.race.difficulty = 0.9f;
	game->options.race.track = 0;
	game->options.race.toy = 0;

	game->general.display.frame = 0;

	tlStringUnload(strings[0]);
	tlDeleteStrings(3, strings);

	game->state= TC_STATE_MAIN,
	tcStateMainIn();
}


void
tcOut(void)
{
	TCGame *game;

	game = tcGame();

	tcStateMainOut();

	tlStringsUnload(game->credits.nstrs, game->credits.strs);
	tlDeleteStrings(game->credits.nstrs, game->credits.strs);

	tlStringsUnload(game->help.nstrs, game->help.strs);
	tlDeleteStrings(game->help.nstrs, game->help.strs);

	tlStringsUnload(game->main.nstrs, game->main.strs);
	tlDeleteStrings(game->main.nstrs, game->main.strs);

	tlStringsUnload(game->general.nsfxs, game->general.sfxs);
	tlDeleteStrings(game->general.nsfxs, game->general.sfxs);

	tlStringsUnload(game->general.ntoys, game->general.toys);
	tlDeleteStrings(game->general.ntoys, game->general.toys);

	tlStringsUnload(8, game->general.tcolors);
	tlDeleteStrings(8, game->general.tcolors);

	tlStringsUnload(game->general.ntracks, game->general.tracks);
	tlDeleteStrings(game->general.ntracks, game->general.tracks);

	alDeleteSources(3, game->general.sounds);
	alDeleteBuffers(3, game->general.buffers);

	mlMeshDeleteMaterials(game->general.selector);
	mlMeshUnload(game->general.selector);
	mlDeleteMeshes(1, &game->general.selector);

	mlMaterialDeleteTextures(game->general.fontmat);
	mlMaterialUnload(game->general.fontmat);
	mlDeleteMaterials(1, &game->general.fontmat);

	flFontUnload(game->general.font);
	flDeleteFonts(1, &game->general.font);

	tlStringsUnload(game->general.nfonts, game->general.fontsmat);
	tlDeleteStrings(game->general.nfonts, game->general.fontsmat);

	tlStringsUnload(game->general.nfonts, game->general.fonts);
	tlDeleteStrings(game->general.nfonts, game->general.fonts);

	/*
	{
		ALuint buffer;

		alGetSourcei(game->background.music, AL_BUFFER, (int *) &buffer);
		alDeleteSources(1, &game->background.music);
		alDeleteBuffers(1, &buffer);
	}
	*/

	jmbcDestroyContext();

	dCloseODE();

	alutExit();
}

void
tcKeyboard(unsigned char key, int x, int y)
{
	TCGame *game;

	game = tcGame();

	switch(game->state)
	{
		case TC_STATE_MAIN: tcStateMainKeyboard(key, x, y); break;
		case TC_STATE_OPTIONS: tcStateOptionsKeyboard(key, x, y); break;
		case TC_STATE_TRACK: tcStateTrackKeyboard(key, x, y); break;
		case TC_STATE_TOY: tcStateToyKeyboard(key, x, y); break;
		case TC_STATE_HELP: tcStateHelpKeyboard(key, x, y); break;
		case TC_STATE_CREDITS: tcStateCreditsKeyboard(key, x, y); break;
		case TC_STATE_RACE: tcStateRaceKeyboard(key, x, y); break;
	}

}

void
tcKeyboardUp(unsigned char key, int x, int y)
{
	TCGame *game;

	game = tcGame();

	switch(game->state)
	{
		case TC_STATE_MAIN: tcStateMainKeyboardUp(key, x, y); break;
		case TC_STATE_OPTIONS: tcStateOptionsKeyboardUp(key, x, y); break;
		case TC_STATE_TRACK: tcStateTrackKeyboardUp(key, x, y); break;
		case TC_STATE_TOY: tcStateToyKeyboardUp(key, x, y); break;
		case TC_STATE_HELP: tcStateHelpKeyboardUp(key, x, y); break;
		case TC_STATE_CREDITS: tcStateCreditsKeyboardUp(key, x, y); break;
		case TC_STATE_RACE: tcStateRaceKeyboardUp(key, x, y); break;
	}
}

void
tcSpecial(int key, int x, int y)
{
	TCGame *game;

	game = tcGame();

	switch(game->state)
	{
		case TC_STATE_MAIN: tcStateMainSpecial(key, x, y); break;
		case TC_STATE_OPTIONS: tcStateOptionsSpecial(key, x, y); break;
		case TC_STATE_TRACK: tcStateTrackSpecial(key, x, y); break;
		case TC_STATE_TOY: tcStateToySpecial(key, x, y); break;
		case TC_STATE_HELP: tcStateHelpSpecial(key, x, y); break;
		case TC_STATE_CREDITS: tcStateCreditsSpecial(key, x, y); break;
		case TC_STATE_RACE: tcStateRaceSpecial(key, x, y); break;
	}
}

void
tcSpecialUp(int key, int x, int y)
{
	TCGame *game;

	game = tcGame();

	switch(game->state)
	{
		case TC_STATE_MAIN: tcStateMainSpecialUp(key, x, y); break;
		case TC_STATE_OPTIONS: tcStateOptionsSpecialUp(key, x, y); break;
		case TC_STATE_TRACK: tcStateTrackSpecialUp(key, x, y); break;
		case TC_STATE_TOY: tcStateToySpecialUp(key, x, y); break;
		case TC_STATE_HELP: tcStateHelpSpecialUp(key, x, y); break;
		case TC_STATE_CREDITS: tcStateCreditsSpecialUp(key, x, y); break;
		case TC_STATE_RACE: tcStateRaceSpecialUp(key, x, y); break;
	}
}

void
tcJoystick(unsigned int buttonmask, int x, int y, int z)
{
	TCGame *game;

	game = tcGame();

	switch(game->state)
	{
		/*
		case TC_STATE_MAIN: tcStateMainJoystick(buttonmask, x, y, z); break;
		case TC_STATE_OPTIONS: tcStateOptionsJoystick(buttonmask, x, y, z); break;
		case TC_STATE_TRACK: tcStateTrackJoystick(buttonmask, x, y, z); break;
		case TC_STATE_TOY: tcStateToyJoystick(buttonmask, x, y, z); break;
		case TC_STATE_HELP: tcStateHelpJoystick(buttonmask, x, y, z); break;
		case TC_STATE_CREDITS: tcStateCreditsJoystick(buttonmask, x, y, z); break;
		*/
		case TC_STATE_RACE: tcStateRaceJoystick(buttonmask, x, y, z); break;
		default: break;
	}
}

void
tcReshape(int width, int height)
{
	TCGame *game;

	game = tcGame();

	game->general.display.width = width;
	game->general.display.height = height;
	game->general.display.aspect = (float) game->general.display.width / (float) game->general.display.height;

	glViewport(0, 0, game->general.display.width, game->general.display.height);

	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	gluPerspective(45.0f, game->general.display.aspect, 1.0f, 1000.0f);

	glMatrixMode(GL_MODELVIEW);
}
 
void
tcDisplay(void)
{
	TCGame *game;

	game = tcGame();

	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	glLoadIdentity();

	switch(game->state)
	{
		case TC_STATE_MAIN: tcStateMainFrame(); break;
		case TC_STATE_OPTIONS: tcStateOptionsFrame(); break;
		case TC_STATE_TRACK: tcStateTrackFrame(); break;
		case TC_STATE_TOY: tcStateToyFrame(); break;
		case TC_STATE_HELP: tcStateHelpFrame(); break;
		case TC_STATE_CREDITS: tcStateCreditsFrame(); break;
		case TC_STATE_RACE: tcStateRaceFrame(); break;
	}

	glutSwapBuffers();
	game->general.display.frame++;
}

void
tcTimer(int value)
{
	TCGame *game;

	game = tcGame();

	glutPostRedisplay();
	glutTimerFunc(40, tcTimer, 0);
}

int
main(int argc, char **argv)
{
	int fakeargc = 1; 
	char *fakeargv[] = { "ToyCars", NULL };
	TCGame *game;

/*
	wprintf(L"%ls", L"ToyCars\n");
	wprintf(L"%ls", L"Copyright " PACKAGE_YEAR L" " PACKAGE_AUTHOR L"\n");
	#ifdef TC_SHAREWARE
	wprintf(L"%ls", L"Free Shareware Version - Provided Free Of Charge\n");
	wprintf(L"%ls", L"Order Full Version At: juanmabcsoft@gmail.com\n");
	wprintf(L"%ls", L"EMail With Subject: Order ToyCars\n");
	wprintf(L"%ls", L"Expect Payment Instructions (Mail Check)\n");
	#else
//	wprintf(L"Full Commercial Version - Licensed\n");
//	wprintf(L"Ordered at: juanmabcsoft@gmail.com\n");
//	wprintf(L"Do Not Share or Distribute Without Permission\n");
//	wprintf(L"Number Of Tracks: 9, Number Of Toys: 3\n");
	wprintf(L"%ls", L"Full Free Version - GPL\n");
	wprintf(L"%ls", L"Available at " PACKAGE_HOMEPAGE L"\n");
	wprintf(L"%ls", L"Play & Enjoy!\n");
	wprintf(L"%ls", L"Number Of Tracks: 9, Number Of Toys: 3\n");
	#endif
//	wprintf(L"Full Version Price: 12 Euros\n");
	wprintf(L"%ls", L"Full Free Version - GPL\n");
*/

	if(argc == 2 && !strcmp(argv[1], "--help"))
	{
		wprintf(L"%ls\n", L"ToyCars");
		wprintf(L"%ls\n", L"Options:");
		wprintf(L"\t%ls\n", L"--help: Help.");
		wprintf(L"\t%ls\n", L"--fullscreen: Launch in fullscreen mode.");

		return EXIT_SUCCESS;
	}

	glutInit(&fakeargc, fakeargv);
	alutInit(&fakeargc, fakeargv);
	dInitODE();

	game = tcGame();

	game->options.display.fullscreen = argc == 2 && !strcmp(argv[1], "--fullscreen");
	game->options.display.width = glutGet(GLUT_SCREEN_WIDTH) * 3 / 4;
	//game->options.display.width = 800 * 3 / 4;
	game->options.display.height = glutGet(GLUT_SCREEN_HEIGHT) * 3 / 4;
	//game->options.display.height = 600 * 3 / 4;
	game->options.display.x = (glutGet(GLUT_SCREEN_WIDTH) - game->options.display.width) / 2;
	game->options.display.y = (glutGet(GLUT_SCREEN_HEIGHT) - game->options.display.height) / 2;
	game->options.race.ntoys = 4;

	glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH);
	glutInitWindowPosition(game->options.display.x, game->options.display.y);
	glutInitWindowSize(game->options.display.width, game->options.display.height);
	glutCreateWindow(fakeargv[0]);
	if(game->options.display.fullscreen) glutFullScreen();
	glutDisplayFunc(tcDisplay);
	glutReshapeFunc(tcReshape);
	glutKeyboardFunc(tcKeyboard);
	glutKeyboardUpFunc(tcKeyboardUp);
	glutSpecialFunc(tcSpecial);
	glutSpecialUpFunc(tcSpecialUp);
	glutJoystickFunc(tcJoystick, 40);
	glutTimerFunc(40, tcTimer, 0);
	tcIn();
	atexit(tcOut);
	glutMainLoop();

	return EXIT_SUCCESS;
}
